DM2 – Décodage par syndrome
Ce DM se place dans la continuité du TD sur les Codes linéaires. Si vous avez fait ce TD en entier, l’effort nécessaire à compléter ce DM va être minimal. Il vous est tout de même possible de réussir ce DM sans avoir résolu l’intégralité du TD, en effet vous pouvez vous focaliser sur le décodage du fichier qui vous est fourni dans le challenge sans nécessairement écrire du code qui marche pour n’importe quel code de Hamming.
Le syndrome
Le syndrome est un objet fondamental dans le décodage des codes linéaires. Dans la suite on suppose donné un code linéaire de paramètres , de matrice de parité et de matrice génératrice . Pour nos exemples, nous allons considérer le code de paramètres défini par les matrices suivantes
On rappelle qu’un message est encodé avec le mot de code . Dans notre exemple, le message est encodé par
Le destinataire reçoit un mot bruité , où est un vecteur d’erreur contenant au plus positions d’erreur. Le syndrome du mot est la valeur
où les égalités découlent de la linéarité de la multiplication de matrices et du fait que est la matrice de parité du code (et que donc pour tout mot de code ). Dans notre exemple, en supposant qu’il y ait eu une erreur en quatrième position, on a
Décodage par syndrome
Comme on a vu ci-dessus, le syndrome d’un mot ne dépend que de l’erreur et pas du tout du mot de code . Même sans connaître l’erreur, on peut donc calculer son syndrome en calculant le produit .
Une fois calculé le syndrome , on trouve l’erreur par recherche sur tous les mots d’erreur possibles. Comme notre code est 1-correcteur, les seules erreurs qu’on peut corriger sont celles de poids au plus 1, c’est à dire les erreurs suivantes
qui correspondent aux syndromes suivants
Dans notre exemple, on était tombés sur le syndrome , qui correspond à l’erreur , c’est à dire une erreur en quatrième position.
Pour les codes 1-correcteurs, comme celui de notre exemple, on peut trouver l’erreur directement sans énumérer tous les syndromes possibles. Si le syndrome est zéro, alors nécessairement et il n’y a pas eu d’erreurs. Sinon, on note le vecteur contenant un à la position et partout ailleurs; souvenez vous qu’alors , où est la -ème colonne de . Par exemple
On peut donc trouver l’erreur simplement en cherchant dans la colonne qui correspond au syndrome.
Une fois trouvée l’erreur , on retrouve le mot de code . Il ne reste plus qu’à trouver le mot d’origine tel que . Mais, puisque est sous forme systématique, ceci est immédiat: le mot d’origine apparaît tel quel dans les premières composantes du mot de code. Dans notre exemple
Pour résumer, voici l’algorithme de décodage par syndrome.
Entrée: Un mot bruité , la matrice de parité .
Sortie: Le message d’origine .
- Calculer le syndrome ;
- Chercher l’erreur telle que ;
- Calculer le mot de code ;
- Le message d’origine se trouve dans les premières composantes de .
À vos javac
Votre devoir consiste à écrire un programme qui encode et décode un fichier binaire en utilisant un code de Hamming et le décodage par syndrome. On donne ici des instructions pour vous aider à structurer votre code, vous n’êtes cependant pas obligés de les suivre à la lettre.
-
Écrivez deux fonctions:
- Une fonction qui lit un fichier octet par octet et retourne un tableau de bits (par exemple en utilisant l’objet
Bit
du TD); - Une fonction qui prend un tableau de bits et l’écrit dans un fichier. Si la longueur du tableau n’est pas un multiple de 8, ajoutez assez de 0 à la fin.
- Une fonction qui lit un fichier octet par octet et retourne un tableau de bits (par exemple en utilisant l’objet
Quelques mots sur le codage du fichier: vous ne devez pas le traiter
comme s’il s’agissait d’un fichier de texte. Vous devez le lire en
mode binaire: octet par octet. Les lectures octet par octet peuvent être faites en Java par une boucle comme ceci (le BufferedInputStream
est optionnel, mais il ajoute de l’efficacité sans rendre la programmation plus compliquée):
BufferedInputStream in = new BufferedInputStream(new FileInputStream("source.txt"));
int i;
while ((i = in.read()) != -1) {
byte octet = (byte)i;
...
}
De manière analogue, les écritures octet par octet se font avec
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("dest.txt"));
while (...) {
byte octet = ...
out.write(octet);
}
Pour plus d’informations sur les lectures/écritures de fichiers en mode binaire, allez lire la page Entrées-Sorties en Java.
-
Écrivez une fonction qui:
- Prend en entrée un tableau de bits de longeur arbitraire;
- Le découpe en blocs de bits;
- Code chaque bloc en utilisant le code de Hamming ;
- Renvoie un tableau de bits qui est l’enchaînement des blocs codés
Encore quelques mots sur l’enchaînement des fonctions que vous avez écrites jusqu’à maintenant. Chaque octet du fichier d’origine vous fournit huit bits, ce qui fait deux blocs de 4 bits. Par exemple, le fichier codé en ASCII que vous pouvez télécharger ici contient le texte
Ham
Ce qui correspond aux trois octets (écrits en hexadécimal)
0x48 0x61 0x6d
Cela fait 6 blocs de 4 octets (écrits en binaire, pour changer):
0100 1000 0110 0001 0110 1101
Chaque bloc est encodé sur sept bits, et les résultats sont concaténés, ce qui donne
0100101 1000110 0110110 0001111 0110110 1101100
On obtient bits au total, ce qui n’est pas un multiple de 8. Pour encoder ceci dans un fichier, on ajoute assez de 0 à droite jusqu’à obtenir un multiple de 8 (le multiple suivant est 48). Le résultat est donc le fichier, que vous pouvez télécharger ici, contenant les octets suivants
01001011 00011001 10110000 11110110 11011011 00000000
soit, en héxadécimal,
0x4b 0x19 0xb0 0xf6 0xdb 0x00
Ceci n’est évidemment pas un fichier de texte lisible (voici par exemple le caractère 0xd0
: Ð). Vous ne pourrez
donc récupérer le texte d’origine qu’après avoir implanté le décodage. Pour vous aider à débugger votre programme, vous pouvez utiliser un hex editor comme http://www.wxhexeditor.org/: les hex editors sont des programmes qui affichent le contenu binaire d’un fichier quelconque sous forme hexadécimale. Sous linux la commande hd
fait la même chose.
-
Écrivez une fonction qui prend un tableau de bits et qui y ajoute une erreur au plus tous les 7 bits. Vous pouvez utiliser la fonction
int alea = (int)(Math.random() * 7);
pour obtenir un entier aléatoire entre 0 et 7.
-
Écrivez une fonction qui
- Prend en entrée un tableau de bits de longeur arbitraire;
- Le découpe en blocs de bits;
- Decode chaque bloc en utilisant un décodage par syndrome;
- Renvoie un tableau de bits qui est l’enchaînement des blocs décodés
Vérifiez votre programme en encodant un fichier, en y ajoutant des erreurs et en décodant (avec et sans erreurs ajoutées).
- Votre mission: visitez cette page et décodez le fichier binaire qui vous est proposé. ATTENTION: le fichier a été encodé avec un code de Hamming comme décrit précédemment (découpage des octes en bits, concaténation, etc.), mais pas forcément avec le code . Vous devez donc faire en sorte que votre code puisse gérer des codes de Hamming différents (ce qui à priori est gagné si vous avez complété le TD sur les Codes linéaires).
Déposez votre code source et le texte déchiffré dans la boîte de dépôt sur e-campus 2 (si e-campus ne devait pas marcher, envoyez-les par mail au professeur). La date limite pour envoyer vos fichiers est le jeudi 5 Avril à 4h du matin. Un point de pénalité pour chaque heure de retard: le 5 Avril à 23h59 c’est votre dernière chance!